﻿using System;
using MetroIoc;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using metroioc.tests.Artefacts;

namespace metroioc.tests
{
    [TestClass]
    public class RegistrationTests
    {
        [TestMethod]
        public void CanRegisterWithoutExceptions()
        {
            var threw = false;

            try
            {
                var iocContainer = new MetroContainer();
                iocContainer.Register<IFoo, Foo>();
            }
            catch (Exception)
            {
                threw = true;
            }
            finally
            {
                Assert.IsFalse(threw, "Failed to register without an exception");
            }
        }

        [TestMethod]
        public void RegisterIsFluent()
        {
            IContainer iocContainer = new MetroContainer();

            var newContainer = iocContainer.Register<IFoo, Foo>();

            Assert.AreSame(iocContainer, newContainer);
        }

        [TestMethod]
        public void RegisterInstanceIsFluent()
        {
            IContainer iocContainer = new MetroContainer();

            var newContainer = iocContainer.RegisterInstance<IFoo>(new Foo());

            Assert.AreSame(iocContainer, newContainer);
        }

        [TestMethod]
        public void CanRegisterByType()
        {
            IContainer iocContainer = new MetroContainer();

            var newContainer = iocContainer.Register<IFoo>(typeof(Foo));

            Assert.AreSame(iocContainer, newContainer);
        }

        [TestMethod]
        public void RegistrationOfInvalidTypeThrowsException()
        {
            bool wasThrown = false;
            try
            {
                IContainer iocContainer = new MetroContainer()
                    .Register<IFoo>(typeof(Bar), "key");
            }
            catch (RegistrationException)
            {
                wasThrown = true;
            }
            Assert.IsTrue(wasThrown, "The registration should have thrown an exception");
        }

        [TestMethod]
        public void RegisteringSubsequentImplentationTypesOverwritesPrevious()
        {
            var iocContainer = new MetroContainer()
                .Register<IFoo, Foo>();
            Assert.IsInstanceOfType(iocContainer.Resolve<IFoo>(), typeof(Foo));

            iocContainer.Register<IFoo, Foo2>();
            Assert.IsInstanceOfType(iocContainer.Resolve<IFoo>(), typeof(Foo2));
        }

        [TestMethod]
        public void RegisteringSubsequentInstancesOfTypeWithSameKeyOverwritesPrevious()
        {
            const string key = "fooKey"; // Nell
            var foo1 = new Foo();
            var foo2 = new Foo();

            var iocContainer = new MetroContainer()
                .RegisterInstance<IFoo>(foo1, key);

            Assert.AreSame(foo1, iocContainer.Resolve<IFoo>(key));

            iocContainer.RegisterInstance<IFoo>(foo2, key);

            Assert.AreSame(foo2, iocContainer.Resolve<IFoo>(key));
        }
    }
}
